package com.google.code.mergeinformer.model;

import com.google.code.mergeinformer.constraint.CvsUrl;
import com.google.code.mergeinformer.util.StringUtils;
import org.hibernate.validator.constraints.NotBlank;

import javax.persistence.*;
import javax.validation.constraints.Min;
import javax.validation.constraints.Size;
import java.util.*;

/**
 * @author Dmitry Golubev
 */
@NamedQueries({
        @NamedQuery(name = "Task.byShortNames", query = "SELECT t FROM Task t WHERE t.project.shortName = :projectShortName AND t.shortName = :taskShortName"),
        @NamedQuery(name = "Task.isNameBusy", query = "SELECT COUNT(t) FROM Task t WHERE t.project.shortName = :projectShortName AND t.name = :taskName"),
        @NamedQuery(name = "Task.isShortNameBusy", query = "SELECT COUNT(t) FROM Task t WHERE t.project.shortName = :projectShortName AND t.shortName = :taskShortName")
})
@Entity
@Table(name = "task")
public class Task extends DefaultEntity {

    @NotBlank
    @Size(max = 64)
    @Column(name = "name")
    private String name;

    @NotBlank
    @Size(max = 32)
    @Column(name = "short_name", nullable = false)
    private String shortName;

    @NotBlank
    @Size(max = 255)
    @CvsUrl
    @Column(name = "url_from")
    private String urlFrom;

    @NotBlank
    @Size(max = 255)
    @CvsUrl
    @Column(name = "url_to")
    private String urlTo;

    @Min(60)
    @Column(name = "exec_interval", nullable = false)
    private Long executionInterval = 60L;

    @ManyToOne(optional = false)
    @JoinColumn(name = "id_project")
    private Project project;

    @Column(name = "executed")
    @Temporal(TemporalType.TIMESTAMP)
    private Date executed;

    @Column(name = "stacktrace")
    private String stackTrace;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "task")
    @OrderBy("timestamp desc")
    private List<Revision> unmergedRevisions = new LinkedList<>();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = StringUtils.normalize(name);
    }

    public String getShortName() {
        return shortName;
    }

    public void setShortName(String shortName) {
        this.shortName = StringUtils.normalize(shortName);
    }

    public String getUrlFrom() {
        return urlFrom;
    }

    public void setUrlFrom(String from) {
        this.urlFrom = from;
    }

    public String getUrlTo() {
        return urlTo;
    }

    public void setUrlTo(String to) {
        this.urlTo = to;
    }

    public Long getExecutionInterval() {
        return executionInterval;
    }

    public void setExecutionInterval(Long checkInterval) {
        this.executionInterval = checkInterval;
    }

    public Project getProject() {
        return project;
    }

    void setProject(Project project) {
        this.project = project;
    }

    public Date getExecuted() {
        return executed;
    }

    public void setExecuted(Date executed) {
        this.executed = executed;
    }

    public List<Revision> getUnmergedRevisions() {
        return unmergedRevisions;
    }

    public String getStackTrace() {
        return stackTrace;
    }

    public void setStackTrace(String stackTrace) {
        this.stackTrace = stackTrace;
    }

    public void replaceRevisions(List<Revision> revisions) {
        unmergedRevisions.clear();
        for (Revision revision : revisions) {
            final Revision rev = new Revision(
                    revision.getNumber(),
                    new Date(revision.getTimestamp().getTime()),
                    revision.getAuthor(),
                    revision.getComment()
            );
            rev.setTask(this);
            unmergedRevisions.add(rev);
        }
        Collections.sort(unmergedRevisions, Collections.reverseOrder());
    }

    public Set<String> getRevisionsAuthors() {
        final Set<String> users = new TreeSet<>();
        for (Revision revision : getUnmergedRevisions()) {
            users.add(revision.getAuthor());
        }
        return users;
    }

    public Task copyAttributes(Task task) {
        name = task.name;
        shortName = task.shortName;
        urlFrom = task.urlFrom;
        urlTo = task.urlTo;
        executionInterval = task.executionInterval;
        return this;
    }
}
